package com.lb.uts.web;

import com.github.pagehelper.PageInfo;
import com.lb.uts.annotation.Modify;
import com.lb.uts.constants.UTSConstants;
import com.lb.uts.entity.*;
import com.lb.uts.entity.*;
import com.lb.uts.service.IScheduleJobService;
import com.lb.uts.service.ISystemService;
import com.lb.uts.constants.BaseResponse;
import com.lb.uts.entity.*;
import com.lb.uts.service.IActiveClientService;
import com.lb.uts.util.IdUtils;
import com.lb.uts.util.RequestUtils;
import com.lb.uts.entity.System;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronExpression;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/* 任务管理 */
@Controller
@RequestMapping("jobInfo")
public class ScheduleJobManagerController extends UtsBaseController {

    private static final Logger logger = LoggerFactory.getLogger(ScheduleJobManagerController.class);

    @Autowired
    private IScheduleJobService scheduleJobService;
    @Autowired
    private ISystemService systemService;

    @Autowired
    private IActiveClientService activeClientService;

    /**
     * list页面
     */
    @RequestMapping("list")
    public String list(@ModelAttribute("jobSearch") JobSearch jobSearch, @RequestParam(value = "pageNum", defaultValue = "1") int pageNo, @RequestParam(value = "pageSize", defaultValue = "10") int pageSize, Model model) {
        PageInfo<ScheduleJob> pageInfo = scheduleJobService.queryList(jobSearch, pageNo, pageSize);
        model.addAttribute("page", pageInfo);
        model.addAttribute("systemList", systemService.queryByEntity(new System()));
        return "jobInfo/list";
    }

    /**
     * 立即执行
     */
    @RequestMapping("executeJob")
    @ResponseBody
    public BaseResponse executeJob(@Valid @NotEmpty(message = "jobId不可以为空") String jobId) throws Exception {
        scheduleJobService.executeJob(jobId);
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 保存任务
     */
    @ResponseBody
    @RequestMapping("saveJob")
    @Validated
    @Modify
    public BaseResponse saveJob(ScheduleJob scheduleJob, Integer concurrentCount) throws SchedulerException {
        logger.info("新建任务:" + scheduleJob.toString());
        if (!isValidExpression(scheduleJob.getCronExpression())) {
            return wrapErrResp(BaseResponse.class, "Corn格式错误");
        }
        String emails = scheduleJob.getAlarmEmail();
        if (StringUtils.isNotBlank(emails)) {
            String[] emailsList = emails.split(",");
            for (String email : emailsList) {
                if (!emailFormat(email)) {
                    return wrapErrResp(BaseResponse.class, email + "格式错误");
                }
            }
        }
        if ("01".equals(scheduleJob.getPolicyType())) {
            scheduleJob.setSlave("01");
        }
        int num = scheduleJobService.saveJobInfo(scheduleJob, concurrentCount);
        return num == 1 ? wrapSuccessResp(BaseResponse.class) : wrapErrResp(BaseResponse.class, "新增失败");
    }

    /**
     * 更新任务
     */
    @ResponseBody
    @RequestMapping("updateJob")
    @Validated
    @Modify
    public BaseResponse updateJob(ScheduleJob scheduleJob, Integer concurrentCount) throws SchedulerException {
        if (!isValidExpression(scheduleJob.getCronExpression())) {
            return wrapErrResp(BaseResponse.class, "Corn格式错误");
        }
        //对于多个邮箱格式验证
        String emails = scheduleJob.getAlarmEmail();
        if (StringUtils.isNotBlank(emails)) {
            String[] emailsList = emails.split(",");
            for (String email : emailsList) {
                if (!emailFormat(email)) {
                    return wrapErrResp(BaseResponse.class, email + "格式错误");
                }
            }
        }
        logger.info("更新任务:" + scheduleJob.toString());
        if ("01".equals(scheduleJob.getPolicyType())) {
            scheduleJob.setSlave("01");
        }
        scheduleJobService.updateJob(scheduleJob, concurrentCount);
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 暂停任务
     */
    @ResponseBody
    @RequestMapping("pauseJob")
    @Validated
    @Modify
    public BaseResponse pauseJob(@NotEmpty(message = "jobId不能为空") String jobId) throws SchedulerException {
        scheduleJobService.pauseJob(jobId);
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 启动任务
     *
     * @param jobId
     * @return
     * @throws SchedulerException
     */
    @ResponseBody
    @RequestMapping("resumeJob")
    @Validated
    @Modify
    public BaseResponse resumeJob(@NotEmpty(message = "jobId不能为空") String jobId) throws SchedulerException {
        scheduleJobService.resumeJob(jobId);
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 删除一个任务
     *
     * @param jobId
     * @return
     * @throws SchedulerException
     */
    @ResponseBody
    @RequestMapping("deleteJob")
    @Validated
    @Modify
    public BaseResponse deleteJob(@NotEmpty(message = "jobId不能为空") String jobId) throws SchedulerException {
        scheduleJobService.deleteJob(jobId);
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 不通过后台，想要删除一个任务调用
     *
     * @param jobName
     * @param jobGroup
     * @return
     * @throws SchedulerException
     */
    @ResponseBody
    @RequestMapping("deleteJobNoPermissions")
    @Validated
    @Modify
    public BaseResponse deleteJobNoPermissions(@NotEmpty(message = "jobName不能为空") String jobName, @NotEmpty(message = "jobGroup不能为空") String jobGroup) throws SchedulerException {
        ScheduleJob scheduleJob = scheduleJobService.selectUniqeJob(jobName, jobGroup);
        if (scheduleJob == null) {
            return wrapErrResp(BaseResponse.class, "任务不存在");
        }
        scheduleJobService.deleteJob(scheduleJob.getJobId());
        return wrapSuccessResp(BaseResponse.class);
    }

    /**
     * 编辑任务
     *
     * @param jobId
     * @return
     */
    @ResponseBody
    @RequestMapping("editJob")
    @Validated
    public Map<String, Object> editJob(@NotEmpty(message = "jobId不能为空") String jobId) {
        ScheduleJob scheduleJob = scheduleJobService.getById(jobId);
        Map<String, Object> result = new HashMap<>();
        if (scheduleJob == null) {
            result.put("returnCode", "0001");
            result.put("returnMsg", "记录不存在");
        } else {
            result.put("returnCode", UTSConstants.SUCCESS_CODE);
            result.put("job", scheduleJob);
        }
        return result;
    }

    /**
     * 当执行器启动的时候，调用这个接口完成执行器和任务的注册
     */
    @ResponseBody
    @RequestMapping("register")
    @Validated
    @Modify
    public String register(@RequestBody ClientDetail clientDetail, HttpServletRequest request) throws SchedulerException {
        logger.info("接受的数据:" + clientDetail.toString());
        //先插入active client
        String systemName = clientDetail.getSystemName();
        ActiveClient activeClient = new ActiveClient();
        activeClient.setId(IdUtils.nextUUID());
        activeClient.setSystemName(systemName);
        activeClient.setWeight(clientDetail.getWeight());
        String ip = RequestUtils.getRemoteIP(request) + ":" + request.getRemotePort();
        activeClient.setIp(ip);
        activeClient.setCreateTime(LocalDateTime.now());
        int num = activeClientService.count(ip, systemName);
        if (num <= 0) {
            try {
                num = activeClientService.insert(activeClient);
                if (num <= 0) {
                    return "FAIL";
                }
            } catch (Exception e) {
                logger.error("激活异常：", e);
            }
        }
        //在插入job
        List<ScheduleJob> scheduleJobList = clientDetail.getTaskJobDetailsList();
        List<ScheduleJob> failList = new ArrayList<>();
        for (ScheduleJob scheduleJob : scheduleJobList) {
            num = scheduleJobService.selectUniqe(scheduleJob.getJobName(), scheduleJob.getJobGroup());
            if (num >= 1) {
                continue;
            }
            try {
                scheduleJob.setSystemName(systemName);
                if ("01".equals(scheduleJob.getPolicyType())) {
                    scheduleJob.setSlave("01");
                }
                scheduleJobService.saveJobInfo(scheduleJob, scheduleJob.getConcurrentNum());
            } catch (Exception e) {
                logger.error("添加任务异常：", e);
                failList.add(scheduleJob);
            }
        }
        if (failList.size() > 0) {
            logger.error(String.format("failList count:%s", failList.size()));
        }
        return "SUCCESS";
    }


    /**
     * 支持注册单个任务
     */
    @ResponseBody
    @RequestMapping("registerJob")
    @Validated
    @Modify
    public String registerJob(@RequestBody ScheduleJob scheduleJob, HttpServletRequest request) throws SchedulerException {
        String systemName = scheduleJob.getSystemName();
        ActiveClient activeClient = new ActiveClient();
        activeClient.setId(IdUtils.nextUUID());
        activeClient.setSystemName(systemName);
        String ip = RequestUtils.getRemoteIP(request) + ":" + scheduleJob.getVersion();
        activeClient.setIp(ip);
        activeClient.setCreateTime(LocalDateTime.now());
        int num = activeClientService.count(ip, systemName);
        if (num <= 0) {
            try {
                num = activeClientService.insert(activeClient);
                if (num <= 0) {
                    return "FAIL";
                }
            } catch (Exception e) {
                logger.error("注册执行器失败");
            }
        }
        num = scheduleJobService.saveJobInfo(scheduleJob, scheduleJob.getConcurrentNum());
        return num >= 0 ? "SUCCESS" : "FAIL";
    }

    public static boolean isValidExpression(String cronExpression) {

        try {
            new CronExpression(cronExpression);
        } catch (ParseException pe) {
            return false;
        }

        return true;
    }

    public static boolean emailFormat(String email) {
        boolean tag = true;
        if (!email.matches("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+")) {
            tag = false;
        }
        return tag;
    }

    /**
     * 接受其他的调度器，完成缓存的刷新
     *
     * @return
     */
    @Modify
    @RequestMapping("modify")
    public String modify() {
        return "SUCCESS";
    }

}
